package com.bugreport.configuration;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.unitils.UnitilsJUnit4;
import org.unitils.spring.annotation.SpringApplicationContext;
import org.unitils.spring.annotation.SpringBeanByType;

import com.bugreport.configuration.BugTrackerConfiguration;
import com.bugreport.configuration.BugTrackerConfigurationLoader;
import com.bugreport.test.utils.BugTrackerTestConfiguration1;
import com.bugreport.test.utils.BugTrackerTestConfiguration2;
import com.bugreport.utils.BugReportException;

public class BTCLLoadConfigurationsTestCase extends UnitilsJUnit4 {

	private static final Logger logger = Logger.getLogger(BTCLLoadConfigurationsTestCase.class);

	private final String type1 = "type1";
	private final String type2 = "type2";

	private final String config1url = "http://www.foo.bar";
	private final String config2url = "www.bar.foo";
	private final String config3url = "https://www.foo.bar";

	@SpringApplicationContext("com/bugreport/configuration/BTCLoadConfigurationsTestCase-spring.xml")
	private ApplicationContext applicationContext;

	@SpringBeanByType
	private BugTrackerConfigurationLoader configLoader;

	@Test
	public void loadConfigurationsSuccessfully() throws BugReportException {

		// Given, unordered list of properties
		Properties properties = new Properties();
		properties.setProperty("1.type", type1);
		properties.setProperty("1.urlpatternmatcher", config1url);

		properties.setProperty("3.type", type1);
		properties.setProperty("3.urlpatternmatcher", config3url);

		properties.setProperty("2.type", type2);
		properties.setProperty("2.urlpatternmatcher", config2url);

		// When
		Map<Integer, BugTrackerConfiguration> configs = BugTrackerConfigurationLoader.load(applicationContext,
				properties);

		// Then
		verifyConfigurationLoading(configs);
	}

	@Test
	public void failToLoadInexistingConfigurationType() {

		// Given
		Properties properties = new Properties();
		properties.setProperty("1.type", "inexisting");
		properties.setProperty("1.urlpatternmatcher", "http://www.foo.bar");

		try {

			// When
			BugTrackerConfigurationLoader.load(applicationContext, properties);

			fail("Expected exception");

		} catch (BugReportException ex) {

			// Then
			assertNotNull(ex);
			assertEquals(102, ex.getCode());
			
			logger.debug(ex.getMessage());
		}
	}

	@Test
	public void loadConfigurationsByDefaultSuccessfully() throws BugReportException {

		// Given
		// Automatically-Spring-instantiated configuration loader

		// When
		Map<Integer, BugTrackerConfiguration> configs = configLoader.getConfigurations();

		// Then
		verifyConfigurationLoading(configs);
	}

	private void verifyConfigurationLoading(Map<Integer, BugTrackerConfiguration> configs) {

		assertNotNull(configs);
		assertEquals(3, configs.size());

		assertTrue(configs.containsKey(1));
		assertTrue(configs.containsKey(2));
		assertTrue(configs.containsKey(3));

		assertTrue(configs.get(1) instanceof BugTrackerTestConfiguration1);
		assertTrue(configs.get(2) instanceof BugTrackerTestConfiguration2);
		assertTrue(configs.get(3) instanceof BugTrackerTestConfiguration1);

		assertEquals(new Integer(1), configs.get(1).getIdConfig());
		assertEquals(new Integer(2), configs.get(2).getIdConfig());
		assertEquals(new Integer(3), configs.get(3).getIdConfig());
		
		assertEquals(type1, configs.get(1).getBugTrackerKey());
		assertEquals(type2, configs.get(2).getBugTrackerKey());
		assertEquals(type1, configs.get(3).getBugTrackerKey());

		assertEquals(config1url, configs.get(1).getUrlPatternMatcher());
		assertEquals(config2url, configs.get(2).getUrlPatternMatcher());
		assertEquals(config3url, configs.get(3).getUrlPatternMatcher());

		Integer index = 1;
		for (Integer key : configs.keySet()) {
			assertEquals(index++, key);
		}
	}
}
